package main

import (
	"fmt"
	"math"
	"reflect"
	"runtime"
)

func main() {
	//单返回值函数
	fmt.Println(eval(3, 4, "+"))
	fmt.Println()

	//多返回值函数
	q, r := div(4, 3)
	fmt.Println("div res:", q, r)
	fmt.Println()

	//函数式编程(函数的参数也是一个函数)
	//main.pow main包里面的pow函数
	fmt.Println(apply(pow, 2, 3))
	//main.main.func1 main包下的main方法中的func1(匿名, 从func1开始递增)
	fmt.Println(apply(func(a int, b int) int {
		return int(math.Pow(float64(a), float64(b)))
	}, 3, 4))
	fmt.Println()

	//可变参数
	fmt.Println(sum(1, 2, 3, 4, 5))
	fmt.Println()
}

//一个返回值的函数
func eval(a, b int, op string) (int, error) {
	switch op {
	case "+":
		return a + b, nil
	case "-":
		return a - b, nil
	case "*":
		return a * b, nil
	case "/":
		// _ 忽略不需要的值
		q, _ := div(a, b)
		return q, nil
	default:
		return 0, fmt.Errorf("unsupported operation: %s", op)
	}
}

//两个返回值的函数
func div(a, b int) (q, r int) {
	//quotient remainder
	//分别返回商和余数

	/*
		//这种方式不适合方法体比较长的情况(不容易看到哪里赋值/修改了)
		q = a / b
		r = a % b
		//这里会直接return q 和 r
		return
	*/

	return a / b, a % b
}

//可变参数
func sum(digits ...int) int {
	result := 0
	for i := range digits {
		result += digits[i]
	}
	return result
}

//函数式编程
func apply(op func(int, int) int, a, b int) int {
	p := reflect.ValueOf(op).Pointer()
	opName := runtime.FuncForPC(p).Name()
	fmt.Printf("Calling function %s with args "+
		"(%d, %d) \n", opName, a, b)
	return op(a, b)
}

func pow(a, b int) int {
	return int(math.Pow(float64(a), float64(b)))
}
